home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / base / net-tool.32- / net-tool / net-tools-1.32-alpha / ifconfig.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-15  |  21.2 KB  |  849 lines

  1. /*
  2.  * ifconfig    This file contains an implementation of the command
  3.  *        that either displays or sets the characteristics of
  4.  *        one or more of the system's networking interfaces.
  5.  *
  6.  * Usage:    ifconfig [-a] [-i] [-v] interface
  7.  *            [inet address]
  8.  *            [ax25] [hw] address]
  9.  *            [metric NN] [mtu NN]
  10.  *            [trailers] [-trailers]
  11.  *            [arp] [-arp]
  12.  *            [netmask aa.bb.cc.dd]
  13.  *            [dstaddr aa.bb.cc.dd]
  14.  *            [mem_start NN] [io_addr NN] [irq NN]
  15.  *            [[-] broadcast [aa.bb.cc.dd]]
  16.  *            [[-]pointopoint [aa.bb.cc.dd]]
  17.  *            [up] [down] ...
  18.  *
  19.  * Version:    ifconfig 1.22 (1996-05-09)
  20.  *
  21.  * Author:    Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
  22.  *        Copyright 1993 MicroWalt Corporation
  23.  *
  24.  *        This program is free software; you can redistribute it
  25.  *        and/or  modify it under  the terms of  the GNU General
  26.  *        Public  License as  published  by  the  Free  Software
  27.  *        Foundation;  either  version 2 of the License, or  (at
  28.  *        your option) any later version.
  29.  */
  30. #include <sys/types.h>
  31. #include <sys/socket.h>
  32. #include <sys/ioctl.h>
  33. #include <linux/netdevice.h>
  34. #include <linux/if.h>
  35. #include <linux/if_arp.h>
  36. #include <linux/if_ether.h>
  37. #include <linux/ipx.h>
  38. #include <stdio.h>
  39. #include <errno.h>
  40. #include <fcntl.h>
  41. #include <ctype.h>
  42. #include <stdlib.h>
  43. #include <string.h>
  44. #include <unistd.h>
  45. #include "net-support.h"
  46. #include "pathnames.h"
  47. #include "version.h"
  48. #include "config.h"
  49. #include "net-locale.h"
  50.  
  51.  
  52. struct interface {
  53.   char            name[IFNAMSIZ];        /* interface name     */
  54.   short            type;            /* if type         */
  55.   short            flags;            /* various flags     */
  56.   int            metric;            /* routing metric     */
  57.   int            mtu;            /* MTU value         */
  58.   struct ifmap        map;            /* hardware setup     */
  59.   struct sockaddr    addr;            /* IP address         */
  60.   struct sockaddr    dstaddr;        /* P-P IP address     */
  61.   struct sockaddr    broadaddr;        /* IP broadcast address     */
  62.   struct sockaddr    netmask;        /* IP network mask     */
  63.   struct sockaddr    ipxaddr_bb;        /* IPX network address   */
  64.   struct sockaddr    ipxaddr_sn;        /* IPX network address   */
  65.   struct sockaddr    ipxaddr_e3;        /* IPX network address   */
  66.   struct sockaddr    ipxaddr_e2;        /* IPX network address   */
  67.   struct sockaddr    ddpaddr;        /* Appletalk DDP address */
  68.   int            has_ip;
  69.   int            has_ipx_bb;
  70.   int            has_ipx_sn;
  71.   int            has_ipx_e3;
  72.   int            has_ipx_e2;
  73.   int            has_ax25;
  74.   int            has_ddp;
  75.   char            hwaddr[32];        /* HW address         */
  76.   struct enet_statistics stats;            /* statistics         */
  77. };
  78.  
  79.   
  80. char *Release = RELEASE,
  81.      *Version = "ifconfig 1.22 (1996-05-09)";
  82.  
  83.  
  84. int opt_a = 0;                /* show all interfaces        */
  85. int opt_i = 0;                /* show the statistics        */
  86. int opt_v = 0;                /* debugging output flag    */
  87. int skfd = -1;                /* generic raw socket desc.    */
  88. int ipx_sock = -1;            /* IPX socket            */
  89. int ax25_sock = -1;            /* AX.25 socket            */
  90. int inet_sock = -1;            /* INET socket            */
  91. int ddp_sock = -1;            /* Appletalk DDP socket        */
  92. int addr_family = 0;            /* currently selected AF    */
  93.  
  94.  
  95. static void
  96. ife_print(struct interface *ptr)
  97. {
  98.   struct aftype *ap;
  99.   struct hwtype *hw;
  100.   int hf;
  101.   char *dispname=NLS_CATSAVE (catfd, ifconfigSet, ifconfig_over, "overruns");
  102.   static struct aftype *ipxtype=NULL, *ddptype=NULL;
  103.   
  104.   ap = get_afntype(ptr->addr.sa_family);
  105.   if (ap == NULL) ap = get_afntype(0);
  106.  
  107.   hf=ptr->type;
  108.  
  109.   if(strncmp(ptr->name,"lo",2)==0)
  110.       hf=255;
  111.       
  112.   if(hf==ARPHRD_CSLIP || hf==ARPHRD_CSLIP6)
  113.   {
  114. #if NLS
  115.         /* NLS must free dispname */
  116.         free (dispname);
  117. #endif
  118.       /* Overrun got reused: BAD - fix later */
  119.       dispname=NLS_CATSAVE (catfd, ifconfigSet, ifconfig_compress, "compressed");
  120.   }
  121.       
  122.   hw = get_hwntype(hf);
  123.   if (hw == NULL) hw = get_hwntype(-1);
  124.  
  125.   printf(NLS_CATGETS(catfd, ifconfigSet, ifconfig_link, "%-8.8s  Link encap:%s  "),
  126.      ptr->name, hw->title);
  127.   if (hw->sprint != NULL) {
  128.     printf(NLS_CATGETS(catfd, ifconfigSet, ifconfig_hw, "HWaddr %s")
  129.            , hw->print(ptr->hwaddr));
  130.   }
  131.   printf(NLS_CATGETS(catfd, ifconfigSet, ifconfig_adr,
  132.              "\n          %s addr:%s"), ap->name, ap->sprint(&ptr->addr, 1));
  133.   if (ptr->flags & IFF_POINTOPOINT) {
  134.     printf(NLS_CATGETS(catfd, ifconfigSet, ifconfig_pap, "  P-t-P:%s  "),
  135.            ap->sprint(&ptr->dstaddr, 1));
  136.   } else {
  137.     printf(NLS_CATGETS(catfd, ifconfigSet, ifconfig_bcast, "  Bcast:%s  "),
  138.            ap->sprint(&ptr->broadaddr, 1));
  139.   }
  140.   printf(NLS_CATGETS(catfd, ifconfigSet, ifconfig_mask, "Mask:%s\n"),
  141.              ap->sprint(&ptr->netmask, 1));
  142.   
  143.   if(ipxtype==NULL)
  144.       ipxtype=get_afntype(AF_IPX);
  145.   if(ipxtype!=NULL)
  146.   {
  147.       if(ptr->has_ipx_bb)
  148.           printf(NLS_CATGETS(catfd, ifconfigSet, ifconfig_etherII,
  149.                    "          IPX/Ethernet II addr:%s\n"),
  150.                ipxtype->sprint(&ptr->ipxaddr_bb,1));
  151.       if(ptr->has_ipx_sn)
  152.           printf(NLS_CATGETS(catfd, ifconfigSet, ifconfig_SNAP,
  153.                    "          IPX/Ethernet SNAP addr:%s\n"),
  154.                ipxtype->sprint(&ptr->ipxaddr_sn,1));
  155.       if(ptr->has_ipx_e2)
  156.           printf(NLS_CATGETS(catfd, ifconfigSet, ifconfig_8022,
  157.                    "          IPX/Ethernet 802.2 addr:%s\n"),
  158.                ipxtype->sprint(&ptr->ipxaddr_e2,1));
  159.       if(ptr->has_ipx_e3)
  160.           printf(NLS_CATGETS(catfd, ifconfigSet, ifconfig_8023,
  161.                    "          IPX/Ethernet 802.3 addr:%s\n"),
  162.                ipxtype->sprint(&ptr->ipxaddr_e3,1));
  163.   }
  164.   if(ddptype==NULL)
  165.       ddptype=get_afntype(AF_APPLETALK);
  166.   if(ddptype!=NULL)
  167.   {
  168.       if(ptr->has_ddp)
  169.           printf(NLS_CATGETS(catfd, ifconfigSet, ifconfig_talk,
  170.                    "          EtherTalk Phase 2 addr:%s\n"),
  171.                ddptype->sprint(&ptr->ddpaddr,1));
  172.   }
  173.   printf("          ");
  174.   if (ptr->flags == 0) printf(NLS_CATGETS(catfd, ifconfigSet, ifconfig_noflags,
  175.                       "[NO FLAGS] "));
  176.   if (ptr->flags & IFF_UP) printf("UP ");
  177.   if (ptr->flags & IFF_BROADCAST) printf("BROADCAST ");
  178.   if (ptr->flags & IFF_DEBUG) printf("DEBUG ");
  179.   if (ptr->flags & IFF_LOOPBACK) printf("LOOPBACK ");
  180.   if (ptr->flags & IFF_POINTOPOINT) printf("POINTOPOINT ");
  181.   if (ptr->flags & IFF_NOTRAILERS) printf("NOTRAILERS ");
  182.   if (ptr->flags & IFF_RUNNING) printf("RUNNING ");
  183.   if (ptr->flags & IFF_NOARP) printf("NOARP ");
  184.   if (ptr->flags & IFF_PROMISC) printf("PROMISC ");
  185.   if (ptr->flags & IFF_ALLMULTI) printf("ALLMULTI ");
  186.   if (ptr->flags & IFF_SLAVE) printf("SLAVE ");
  187.   if (ptr->flags & IFF_MASTER) printf("MASTER ");
  188.   if (ptr->flags & IFF_MULTICAST) printf("MULTICAST ");
  189.   printf(NLS_CATGETS(catfd, ifconfigSet, ifconfig_mtu, " MTU:%d  Metric:%d\n"),
  190.      ptr->mtu, ptr->metric?ptr->metric:1);
  191.  
  192.  
  193.   /* If needed, display the interface statistics. */
  194.   printf("          ");
  195.   printf(NLS_CATGETS(catfd, ifconfigSet, ifconfig_rx,
  196.              "RX packets:%u errors:%u dropped:%u %s:%u\n"),
  197.      ptr->stats.rx_packets, ptr->stats.rx_errors,
  198.      ptr->stats.rx_dropped, dispname, ptr->stats.rx_fifo_errors);
  199.   printf("          ");
  200.   printf(NLS_CATGETS(catfd, ifconfigSet, ifconfig_tx,
  201.              "TX packets:%u errors:%u dropped:%u %s:%u\n"),
  202.      ptr->stats.tx_packets, ptr->stats.tx_errors,
  203.      ptr->stats.tx_dropped, dispname, ptr->stats.tx_fifo_errors);
  204.  
  205.   if(hf<255 && (ptr->map.irq || ptr->map.mem_start || ptr->map.dma || ptr->map.base_addr))
  206.   {
  207.       printf("          ");
  208.       if(ptr->map.irq)
  209.           printf(NLS_CATGETS(catfd, ifconfigSet, ifconfig_interrupt,
  210.                    "Interrupt:%d "), ptr->map.irq);
  211.       if(ptr->map.base_addr>=0x100)    /* Only print devices using it for I/O maps */
  212.           printf(NLS_CATGETS(catfd, ifconfigSet, ifconfig_base,
  213.                    "Base address:0x%x "), ptr->map.base_addr);
  214.       if(ptr->map.mem_start)
  215.       {
  216.           printf(NLS_CATGETS(catfd, ifconfigSet, ifconfig_mem, "Memory:%lx-%lx "),
  217.               ptr->map.mem_start,ptr->map.mem_end);
  218.       }
  219.       if(ptr->map.dma)
  220.           printf(NLS_CATGETS(catfd, ifconfigSet, ifconfig_dma, "DMA chan:%x "),
  221.                ptr->map.dma);
  222.       printf("\n");
  223.   }
  224.   printf("\n");
  225.  
  226. #if NLS
  227.   /* NLS must free dispname */
  228.   free (dispname);
  229. #endif
  230. }
  231.  
  232.  
  233. static void if_getstats(char *ifname, struct interface *ife)
  234. {
  235.   FILE *f=fopen("/proc/net/dev","r");
  236.   char buf[256];
  237.   char *bp;
  238.   if(f==NULL)
  239.       return;
  240.   while(fgets(buf,255,f))
  241.   {
  242.       bp=buf;
  243.       while(*bp&&isspace(*bp))
  244.           bp++;
  245.       if(strncmp(bp,ifname,strlen(ifname))==0 && bp[strlen(ifname)]==':')
  246.       {
  247.          bp=strchr(bp,':');
  248.          bp++;
  249.          sscanf(bp,"%d %d %d %d %d %d %d %d %d %d %d",
  250.              &ife->stats.rx_packets,
  251.              &ife->stats.rx_errors,
  252.              &ife->stats.rx_dropped,
  253.              &ife->stats.rx_fifo_errors,
  254.              &ife->stats.rx_frame_errors,
  255.              
  256.              &ife->stats.tx_packets,
  257.              &ife->stats.tx_errors,
  258.              &ife->stats.tx_dropped,
  259.              &ife->stats.tx_fifo_errors,
  260.              &ife->stats.collisions,
  261.              
  262.              &ife->stats.tx_carrier_errors
  263.          );
  264.          fclose(f);
  265.          return;
  266.       }
  267.   }
  268.   fclose(f);
  269. }
  270.  
  271. /* Support for fetching an IPX address */
  272.  
  273. static int ipx_getaddr(int sock, int ft, struct ifreq *ifr)
  274. {
  275.     ((struct sockaddr_ipx *)&ifr->ifr_addr)->sipx_type=ft;
  276.     return ioctl(sock, SIOCGIFADDR, ifr);
  277. }
  278.  
  279. /* Fetch the inteface configuration from the kernel. */
  280. static int
  281. if_fetch(char *ifname, struct interface *ife)
  282. {
  283.   struct ifreq ifr;
  284.  
  285.   memset((char *) ife, 0, sizeof(struct interface));
  286.   strcpy(ife->name, ifname);
  287.  
  288.   strcpy(ifr.ifr_name, ifname);
  289.   if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0) return(-1);
  290.   ife->flags = ifr.ifr_flags;
  291.  
  292.   strcpy(ifr.ifr_name, ifname);
  293.   if (ioctl(inet_sock, SIOCGIFADDR, &ifr) < 0) {
  294.     memset(&ife->addr, 0, sizeof(struct sockaddr));
  295.   } else ife->addr = ifr.ifr_addr;
  296.  
  297.   strcpy(ifr.ifr_name, ifname);
  298.   
  299.   if (ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0) {
  300.     memset(ife->hwaddr, 0, 32);
  301.   } else memcpy(ife->hwaddr,ifr.ifr_hwaddr.sa_data,8);
  302.  
  303.   ife->type=ifr.ifr_hwaddr.sa_family;
  304.  
  305.   strcpy(ifr.ifr_name, ifname);
  306.   if (ioctl(skfd, SIOCGIFMETRIC, &ifr) < 0) {
  307.     ife->metric = 0;
  308.   } else ife->metric = ifr.ifr_metric;
  309.  
  310.   strcpy(ifr.ifr_name, ifname);
  311.   if (ioctl(skfd, SIOCGIFMTU, &ifr) < 0) {
  312.     ife->mtu = 0;
  313.   } else ife->mtu = ifr.ifr_mtu;
  314.  
  315.   strcpy(ifr.ifr_name, ifname);
  316.   if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0) {
  317.     memset(&ife->map, 0, sizeof(struct ifmap));
  318.   } else memcpy(&ife->map,&ifr.ifr_map,sizeof(struct ifmap));
  319.  
  320.   strcpy(ifr.ifr_name, ifname);
  321.   if (ioctl(inet_sock, SIOCGIFDSTADDR, &ifr) < 0) {
  322.     memset(&ife->dstaddr, 0, sizeof(struct sockaddr));
  323.   } else ife->dstaddr = ifr.ifr_dstaddr;
  324.  
  325.   strcpy(ifr.ifr_name, ifname);
  326.   if (ioctl(inet_sock, SIOCGIFBRDADDR, &ifr) < 0) {
  327.     memset(&ife->broadaddr, 0, sizeof(struct sockaddr));
  328.   } else ife->broadaddr = ifr.ifr_broadaddr;
  329.  
  330.   strcpy(ifr.ifr_name, ifname);
  331.   if (ioctl(inet_sock, SIOCGIFNETMASK, &ifr) < 0) {
  332.     memset(&ife->netmask, 0, sizeof(struct sockaddr));
  333.   } else ife->netmask = ifr.ifr_netmask;
  334.   
  335.   strcpy(ifr.ifr_name, ifname);
  336.   if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0) {
  337.       memset(&ife->map, 0, sizeof(struct ifmap));
  338.   }
  339.   else ife->map = ifr.ifr_map;
  340.   
  341.   /* DDP address maybe ? */
  342.   strcpy(ifr.ifr_name, ifname);
  343.   if (ioctl(ddp_sock, SIOCGIFADDR, &ifr)==0)
  344.   {
  345.       ife->ddpaddr=ifr.ifr_addr;
  346.       ife->has_ddp=1;
  347.   }
  348.   
  349.   /* Look for IPX addresses with all framing types */
  350.   strcpy(ifr.ifr_name, ifname);
  351.   
  352.   if(!ipx_getaddr(ipx_sock, IPX_FRAME_ETHERII, &ifr))
  353.   {
  354.       ife->has_ipx_bb=1;
  355.       ife->ipxaddr_bb=ifr.ifr_addr;
  356.   }
  357.   strcpy(ifr.ifr_name, ifname);
  358.   if(!ipx_getaddr(ipx_sock, IPX_FRAME_SNAP, &ifr))
  359.   {
  360.       ife->has_ipx_sn=1;
  361.       ife->ipxaddr_sn=ifr.ifr_addr;
  362.   }
  363.   strcpy(ifr.ifr_name, ifname);
  364.   if(!ipx_getaddr(ipx_sock, IPX_FRAME_8023, &ifr))
  365.   {
  366.       ife->has_ipx_e3=1;
  367.       ife->ipxaddr_e3=ifr.ifr_addr;
  368.   }
  369.   strcpy(ifr.ifr_name, ifname);
  370.   if(!ipx_getaddr(ipx_sock, IPX_FRAME_8022, &ifr))
  371.   {
  372.       ife->has_ipx_e2=1;
  373.       ife->ipxaddr_e2=ifr.ifr_addr;
  374.   }
  375.   
  376.   if_getstats(ifname,ife);
  377.   return(0);
  378. }
  379.  
  380.  
  381. static void
  382. if_print(char *ifname)
  383. {
  384.   char buff[1024];
  385.   struct interface ife;
  386.   struct ifconf ifc;
  387.   struct ifreq *ifr;
  388.   int i;
  389.  
  390.   if (ifname == (char *)NULL) {
  391.     ifc.ifc_len = sizeof(buff);
  392.     ifc.ifc_buf = buff;
  393.     if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) {
  394.         fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
  395.         return;
  396.     }
  397.  
  398.     ifr = ifc.ifc_req;
  399.     for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) {
  400.         if (if_fetch(ifr->ifr_name, &ife) < 0) {
  401.             fprintf(stderr, NLS_CATGETS(catfd, ifconfigSet, ifconfig_unkn,
  402.                             "%s: unknown interface.\n"),
  403.                 ifr->ifr_name);
  404.             continue;
  405.         }
  406.  
  407.         if (((ife.flags & IFF_UP) == 0) && !opt_a) continue;
  408.         ife_print(&ife);
  409.     }
  410.   } else {
  411.     if (if_fetch(ifname, &ife) < 0)
  412.         fprintf(stderr, NLS_CATGETS(catfd, ifconfigSet, ifconfig_unkn,
  413.                         "%s: unknown interface.\n"), ifname);
  414.       else ife_print(&ife);
  415.   }
  416. }
  417.  
  418.  
  419. /* Set a certain interface flag. */
  420. static int
  421. set_flag(char *ifname, short flag)
  422. {
  423.   struct ifreq ifr;
  424.  
  425.   strcpy(ifr.ifr_name, ifname);
  426.   if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0) return(-1);
  427.   ifr.ifr_flags |= flag;
  428.   if (ioctl(skfd, SIOCSIFFLAGS, &ifr) < 0) {
  429.     fprintf(stderr, "SIOCSIFFLAGS: %s\n", strerror(errno));
  430.     return(-1);
  431.   }
  432.   return(0);
  433. }
  434.  
  435.  
  436. /* Clear a certain interface flag. */
  437. static int
  438. clr_flag(char *ifname, short flag)
  439. {
  440.   struct ifreq ifr;
  441.  
  442.   strcpy(ifr.ifr_name, ifname);
  443.   if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0) return(-1);
  444.   ifr.ifr_flags &= ~flag;
  445.   if (ioctl(skfd, SIOCSIFFLAGS, &ifr) < 0) {
  446.     fprintf(stderr, "SIOCSIFFLAGS: %s\n", strerror(errno));
  447.     return(-1);
  448.   }
  449.   return(0);
  450. }
  451.  
  452.  
  453. static void
  454. usage(void)
  455. {
  456.   fprintf(stderr, NLS_CATGETS(catfd, ifconfigSet, ifconfig_usage1,
  457.                   "Usage: ifconfig [-a] [-i] [-v] interface\n"));
  458.   fprintf(stderr, NLS_CATGETS(catfd, ifconfigSet, ifconfig_usage2,
  459.                   "                [inet address]\n"));
  460.   fprintf(stderr, NLS_CATGETS(catfd, ifconfigSet, ifconfig_usage3,
  461.                   "                [hw] [ax25 address]\n"));
  462.   fprintf(stderr, "                [metric NN] [mtu NN]\n");
  463.   fprintf(stderr, "                [trailers] [-trailers]\n");
  464.   fprintf(stderr, "                [arp] [-arp]\n");
  465.   fprintf(stderr, "                [netmask aa.bb.cc.dd]\n");
  466.   fprintf(stderr, "                [dstaddr aa.bb.cc.dd]\n");
  467.   fprintf(stderr, "                [mem_start NN] [io_addr NN] [irq NN]\n");
  468.   fprintf(stderr, "                [[-] broadcast [aa.bb.cc.dd]]\n");
  469.   fprintf(stderr, "                [[-]pointopoint [aa.bb.cc.dd]]\n");
  470.   fprintf(stderr, "                [up] [down] ...\n");
  471.   NLS_CATCLOSE(catfd)
  472.   exit(1);
  473. }
  474.  
  475. static void
  476. version(void)
  477. {
  478.   fprintf(stderr,"%s\n%s\n",Release,Version);
  479.   NLS_CATCLOSE(catfd)
  480.   exit(1);
  481. }
  482.  
  483. static int sockets_open()
  484. {
  485.     inet_sock=socket(AF_INET, SOCK_DGRAM, 0);
  486.     ipx_sock=socket(AF_IPX, SOCK_DGRAM, 0);
  487.     ax25_sock=socket(AF_AX25, SOCK_DGRAM, 0);
  488.     ddp_sock=socket(AF_APPLETALK, SOCK_DGRAM, 0);
  489.     /*
  490.      *    Now pick any (exisiting) useful socket family for generic queries
  491.      */
  492.     if(inet_sock!=-1)
  493.         return inet_sock;
  494.     if(ipx_sock!=-1)
  495.         return ipx_sock;
  496.     if(ax25_sock!=-1)
  497.         return ax25_sock;
  498.     /*
  499.      *    If this is -1 we have no known network layers and its time to jump.
  500.      */
  501.      
  502.     return ddp_sock;
  503. }
  504.     
  505. int
  506. main(int argc, char **argv)
  507. {
  508.   struct sockaddr sa;
  509.   char host[128];
  510.   struct aftype *ap;
  511.   struct hwtype *hw;
  512.   struct ifreq ifr;
  513.   int goterr = 0;
  514.   char **spp;
  515.  
  516. #if NLS
  517.   setlocale (LC_MESSAGES, "");
  518.   catfd = catopen ("nettools", MCLoadBySet);
  519. #endif
  520.  
  521.   /* Create a channel to the NET kernel. */
  522.   if ((skfd = sockets_open()) < 0) {
  523.     perror("socket");
  524.     NLS_CATCLOSE(catfd)
  525.     exit(-1);
  526.   }
  527.   /* Find any options. */
  528.   argc--; argv++;
  529.   while (argc && *argv[0] == '-') {
  530.     if (!strcmp(*argv, "-a")) opt_a = 1;
  531.     
  532.     if (!strcmp(*argv, "-v")) opt_v = 1;
  533.     
  534.     if (!strcmp(*argv, "-V") || !strcmp(*argv, "-version") || 
  535.         !strcmp(*argv, "--version")) version();
  536.         
  537.     if (!strcmp(*argv, "-?") || !strcmp(*argv, "-h") || 
  538.         !strcmp(*argv, "-help") || !strcmp(*argv, "--help")) usage();
  539.  
  540.     argv++;
  541.     argc--;
  542.   }
  543.  
  544.   /* Do we have to show the current setup? */
  545.   if (argc == 0) {
  546.     if_print((char *)NULL);
  547.     (void) close(skfd);
  548.     NLS_CATCLOSE(catfd)
  549.     exit(0);
  550.   }
  551.  
  552.   /* No. Fetch the interface name. */
  553.   spp = argv;
  554.   strncpy(ifr.ifr_name, *spp++, IFNAMSIZ);
  555.   if (*spp == (char *)NULL) {
  556.     if_print(ifr.ifr_name);
  557.     (void) close(skfd);
  558.     NLS_CATCLOSE(catfd)
  559.     exit(0);
  560.   }
  561.  
  562.   /* The next argument is either an address family name, or an option. */
  563.   if ((ap = get_aftype(*spp)) == NULL) {
  564.     ap = get_aftype("inet");
  565.   } else spp++;
  566.   addr_family = ap->af;
  567.  
  568.   /* Process the remaining arguments. */
  569.   while (*spp != (char *)NULL) {
  570.     if (!strcmp(*spp, "arp")) {
  571.         goterr |= clr_flag(ifr.ifr_name, IFF_NOARP);
  572.         spp++;
  573.         continue;
  574.     }
  575.  
  576.     if (!strcmp(*spp, "-arp")) {
  577.         goterr |= set_flag(ifr.ifr_name, IFF_NOARP);
  578.         spp++;
  579.         continue;
  580.     }
  581.  
  582.     if (!strcmp(*spp, "trailers")) {
  583.         goterr |= clr_flag(ifr.ifr_name, IFF_NOTRAILERS);
  584.         spp++;
  585.         continue;
  586.     }
  587.  
  588.     if (!strcmp(*spp, "-trailers")) {
  589.         goterr |= set_flag(ifr.ifr_name, IFF_NOTRAILERS);
  590.         spp++;
  591.         continue;
  592.     }
  593.  
  594.     if (!strcmp(*spp, "promisc")) {
  595.         goterr |= set_flag(ifr.ifr_name, IFF_PROMISC);
  596.         spp++;
  597.         continue;
  598.     }
  599.  
  600.     if (!strcmp(*spp, "-promisc")) {
  601.         goterr |= clr_flag(ifr.ifr_name, IFF_PROMISC);
  602.         spp++;
  603.         continue;
  604.     }
  605.  
  606.     if (!strcmp(*spp, "multicast")) {
  607.         goterr |= set_flag(ifr.ifr_name, IFF_MULTICAST);
  608.         spp++;
  609.         continue;
  610.     }
  611.  
  612.     if (!strcmp(*spp, "-multicast")) {
  613.         goterr |= clr_flag(ifr.ifr_name, IFF_MULTICAST);
  614.         spp++;
  615.         continue;
  616.     }
  617.  
  618.     if (!strcmp(*spp, "allmulti")) {
  619.         goterr |= set_flag(ifr.ifr_name, IFF_ALLMULTI);
  620.         spp++;
  621.         continue;
  622.     }
  623.  
  624.     if (!strcmp(*spp, "-allmulti")) {
  625.         goterr |= clr_flag(ifr.ifr_name, IFF_ALLMULTI);
  626.         spp++;
  627.         continue;
  628.     }
  629.  
  630.     if (!strcmp(*spp, "up")) {
  631.         goterr |= set_flag(ifr.ifr_name, (IFF_UP | IFF_RUNNING));
  632.         spp++;
  633.         continue;
  634.     }
  635.  
  636.     if (!strcmp(*spp, "down")) {
  637.         goterr |= clr_flag(ifr.ifr_name, IFF_UP);
  638.         spp++;
  639.         continue;
  640.     }
  641.  
  642.     if (!strcmp(*spp, "metric")) {
  643.         if (*++spp == NULL) usage();
  644.         ifr.ifr_metric = atoi(*spp);
  645.         if (ioctl(skfd, SIOCSIFMETRIC, &ifr) < 0) {
  646.             fprintf(stderr, "SIOCSIFMETRIC: %s\n", strerror(errno));
  647.             goterr = 1;
  648.         }
  649.         spp++;
  650.         continue;
  651.     }
  652.  
  653.     if (!strcmp(*spp, "mtu")) {
  654.         if (*++spp == NULL) usage();
  655.         ifr.ifr_mtu = atoi(*spp);
  656.         if (ioctl(skfd, SIOCSIFMTU, &ifr) < 0) {
  657.             fprintf(stderr, "SIOCSIFMTU: %s\n", strerror(errno));
  658.             goterr = 1;
  659.         }
  660.         spp++;
  661.         continue;
  662.     }
  663.  
  664.     if (!strcmp(*spp, "-broadcast")) {
  665.         goterr |= clr_flag(ifr.ifr_name, IFF_BROADCAST);
  666.         spp++;
  667.         continue;
  668.     }
  669.  
  670.     if (!strcmp(*spp, "broadcast")) {
  671.         if (*++spp != NULL ) {
  672.             strcpy(host, *spp);
  673.             if (ap->input(0, host, &sa) < 0) {
  674.                 ap->herror(host);
  675.                 goterr = 1;
  676.                 spp++;
  677.                 continue;
  678.             }
  679.             memcpy((char *) &ifr.ifr_broadaddr, (char *) &sa,
  680.                         sizeof(struct sockaddr));
  681.             if (ioctl(skfd, SIOCSIFBRDADDR, &ifr) < 0) {
  682.                 fprintf(stderr, "SIOCSIFBRDADDR: %s\n",
  683.                             strerror(errno));
  684.                 goterr = 1;
  685.             }
  686.             spp++;
  687.         }
  688.         goterr |= set_flag(ifr.ifr_name, IFF_BROADCAST);
  689.         continue;
  690.     }
  691.  
  692.     if (!strcmp(*spp, "dstaddr")) {
  693.         if (*++spp == NULL) usage();
  694.         strcpy(host, *spp);
  695.         if (ap->input(0, host, &sa) < 0) {
  696.             ap->herror(host);
  697.             goterr = 1;
  698.             spp++;
  699.             continue;
  700.         }
  701.         memcpy((char *) &ifr.ifr_dstaddr, (char *) &sa,
  702.                         sizeof(struct sockaddr));
  703.         if (ioctl(skfd, SIOCSIFDSTADDR, &ifr) < 0) {
  704.             fprintf(stderr, "SIOCSIFDSTADDR: %s\n",
  705.                         strerror(errno));
  706.             goterr = 1;
  707.         }
  708.         spp++;
  709.         continue;
  710.     }
  711.  
  712.     if (!strcmp(*spp, "netmask")) {
  713.         if (*++spp == NULL) usage();
  714.         strcpy(host, *spp);
  715.         if (ap->input(0, host, &sa) < 0) {
  716.             ap->herror(host);
  717.             goterr = 1;
  718.             spp++;
  719.             continue;
  720.         }
  721.         memcpy((char *) &ifr.ifr_netmask, (char *) &sa,
  722.                         sizeof(struct sockaddr));
  723.         if (ioctl(skfd, SIOCSIFNETMASK, &ifr) < 0) {
  724.             fprintf(stderr, "SIOCSIFNETMASK: %s\n",
  725.                         strerror(errno));
  726.             goterr = 1;
  727.         }
  728.         spp++;
  729.         continue;
  730.     }
  731.  
  732.     if (!strcmp(*spp, "mem_start")) {
  733.         if (*++spp == NULL) usage();
  734.         if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0) {
  735.             goterr = 1;
  736.             continue;
  737.         }
  738.         ifr.ifr_map.mem_start = strtoul(*spp, NULL, 0);
  739.         if (ioctl(skfd, SIOCSIFMAP, &ifr) < 0) {
  740.             fprintf(stderr, "SIOCSIFMAP: %s\n", strerror(errno));
  741.             goterr = 1;
  742.         }
  743.         spp++;
  744.         continue;
  745.     }
  746.  
  747.     if (!strcmp(*spp, "io_addr")) {
  748.         if (*++spp == NULL) usage();
  749.         if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0) {
  750.             goterr = 1;
  751.             continue;
  752.         }
  753.         ifr.ifr_map.base_addr = strtol(*spp, NULL, 0);
  754.         if (ioctl(skfd, SIOCSIFMAP, &ifr) < 0) {
  755.             fprintf(stderr, "SIOCSIFMAP: %s\n", strerror(errno));
  756.             goterr = 1;
  757.         }
  758.         spp++;
  759.         continue;
  760.     }
  761.  
  762.     if (!strcmp(*spp, "irq")) {
  763.         if (*++spp == NULL) usage();
  764.         if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0) {
  765.             goterr = 1;
  766.             continue;
  767.         }
  768.         ifr.ifr_map.irq = atoi(*spp);
  769.         if (ioctl(skfd, SIOCSIFMAP, &ifr) < 0) {
  770.             fprintf(stderr, "SIOCSIFMAP: %s\n", strerror(errno));
  771.             goterr = 1;
  772.         }
  773.         spp++;
  774.         continue;
  775.     }
  776.  
  777.     if (!strcmp(*spp, "-pointopoint")) {
  778.         goterr |= clr_flag(ifr.ifr_name, IFF_POINTOPOINT);
  779.         spp++;
  780.         continue;
  781.     }
  782.  
  783.     if (!strcmp(*spp, "pointopoint")) {
  784.         if (*(spp+1) != NULL) {
  785.             spp++;
  786.             strcpy(host, *spp);
  787.             if (ap->input(0, host, &sa)) {
  788.                 ap->herror(host);
  789.                 goterr = 1;
  790.                 spp++;
  791.                 continue;
  792.             };
  793.             memcpy((char *) &ifr.ifr_dstaddr, (char *) &sa,
  794.                         sizeof(struct sockaddr));
  795.             if (ioctl(skfd, SIOCSIFDSTADDR, &ifr) < 0) {
  796.                 fprintf(stderr, "SIOCSIFDSTADDR: %s\n",
  797.                             strerror(errno));
  798.                 goterr = 1;
  799.             }
  800.         }
  801.         goterr |= set_flag(ifr.ifr_name, IFF_POINTOPOINT);
  802.         spp++;
  803.         continue;
  804.     };
  805.  
  806.     if (!strcmp(*spp, "hw")) {
  807.         if (*++spp == NULL) usage();
  808.         if ((hw = get_hwtype(*spp)) == NULL) usage();
  809.         strcpy(host, *++spp);
  810.         if (hw->input(host, &sa) < 0) {
  811.             ap->herror(host);
  812.             goterr = 1;
  813.             spp++;
  814.             continue;
  815.         }
  816.         memcpy((char *) &ifr.ifr_hwaddr, (char *) &sa,
  817.                         sizeof(struct sockaddr));
  818.         if (ioctl(skfd, SIOCSIFHWADDR, &ifr) < 0) {
  819.             fprintf(stderr, "SIOCSIFHWADDR: %s\n",
  820.                         strerror(errno));
  821.             goterr = 1;
  822.         }
  823.         spp++;
  824.         continue;
  825.     }
  826.  
  827.     /* If the next argument is a valid hostname, assume OK. */
  828.     strcpy(host, *spp);
  829.     if (ap->input(0, host, &sa) < 0) {
  830.         ap->herror(host);
  831.         usage();
  832.     }
  833.  
  834.     memcpy((char *) &ifr.ifr_addr, (char *) &sa, sizeof(struct sockaddr));
  835.     if (ioctl(skfd, SIOCSIFADDR, &ifr) < 0) {
  836.         fprintf(stderr, "SIOCSIFADDR: %s\n", strerror(errno));
  837.             goterr = 1;
  838.     }
  839.     goterr |= set_flag(ifr.ifr_name, (IFF_UP | IFF_RUNNING));
  840.     spp++;
  841.   }
  842.  
  843.   /* Close the socket. */
  844.   (void) close(skfd);
  845.  
  846.   NLS_CATCLOSE(catfd)
  847.   return(goterr);
  848. }
  849.